package com.ruoyi.service.impl;


import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.enums.CellDataTypeEnum;
import com.alibaba.excel.metadata.data.ImageData;
import com.alibaba.excel.metadata.data.WriteCellData;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fasterxml.jackson.core.type.TypeReference;
import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.conver.ExceptionDataConvert;
import com.ruoyi.domain.ExceptionData;
import com.ruoyi.domain.SkuInfo;
import com.ruoyi.dto.ExceptionDataDTO;
import com.ruoyi.dto.ExceptionDataExport;
import com.ruoyi.dto.SkuDTO;
import com.ruoyi.mapper.ExceptionDataMapper;
import com.ruoyi.service.ExceptionDataService;
import com.ruoyi.vo.ExceptionDataExcel;
import com.ruoyi.vo.ExceptionDataExcelVO;
import com.ruoyi.vo.ExceptionDataVO;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.ruoyi.vo.SkuVO;
import lombok.var;
import org.apache.commons.compress.utils.IOUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.net.URL;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @Author:zzm
 * @Date: 2024/9/2 10:43
 */
@Service
public class ExceptionDataServiceImpl extends ServiceImpl<ExceptionDataMapper, ExceptionData> implements ExceptionDataService {



    @Autowired
    private ExceptionDataMapper exceptionDataMapper;
    @Autowired
    private ExceptionDataConvert exceptionDataConvert;

    /**
     * 新增
     * @param dto
     * @return
     */
    @Override
    public Boolean add(ExceptionDataDTO dto) {
        ExceptionData data = exceptionDataConvert.addExceptionDataDTOToEntity(dto);
        data.setFileList(dto.getFileListPut());
//        //获取用户名
        LoginUser loginUser = SecurityUtils.getLoginUser();
        String username = loginUser.getUsername();
        data.setUploadPeople(username);
        data.setCreateBy(username);
        data.setEnter("");
        data.setCreateTime(new Date());
        data.setFlagDel(0);
        return this.save(data);
    }

    /**
     * 修改
     * @param dto
     * @return
     */
    @Override
    public Boolean update(ExceptionDataDTO dto) {
        ExceptionData data = exceptionDataConvert.addExceptionDataDTOToEntity(dto);
        data.setFileList(dto.getFileListPut());
        return this.updateById(data);
    }

    /**
     * 查询列表
     * @param dto
     * @return
     */
    @Override
    public List<ExceptionDataVO> getList(ExceptionData dto) {
        List<ExceptionDataVO> list = exceptionDataMapper.getList(dto.getDate(), dto.getCustomer(),dto.getUploadDepartment(),dto.getWareHouse(),dto.getProblem(),dto.getFlagDel());
        System.out.println(list);
        return list;
    }

    @Override
    public ExceptionDataVO detailsForId(Long id) {
        return exceptionDataMapper.detailsForId(id);
    }

    /**
     * 删除放入回收站
     * @param ids
     */
    @Override
    public void deleteByIds(Long[] ids) {
        for (int i = 0; i < ids.length; i++) {
            exceptionDataMapper.deleteByIds(ids[i]);
        }
    }

    /**
     * 还原回收站数据
     * @param ids
     */
    @Override
    public void backByIds(Long[] ids) {
        for (int i = 0; i < ids.length; i++) {
            exceptionDataMapper.backByIds(ids[i]);
        }
    }

    /**
     * 确认
     * @param ids
     */
    @Override
    public void enterByIds(Long[] ids) {
        LoginUser loginUser = SecurityUtils.getLoginUser();
        String username = loginUser.getUsername();
        for (int i = 0; i < ids.length; i++) {
            exceptionDataMapper.enterByIds(ids[i],username);
        }

    }

    /**
     * 导出模板
     */
    @Override
    public void handleExport(HttpServletResponse response) {
        ExcelUtil<ExceptionDataExport> util = new ExcelUtil<ExceptionDataExport>(ExceptionDataExport.class);
        util.exportExcel(response, null, "异常数据模板");
    }

    /**
     * 导出异常数据
     * @param response
     * @param ids
     */
    @Override
    public void export(HttpServletResponse response, List<Long> ids) throws IOException {
        List<ExceptionDataExcelVO> list = new ArrayList<>();
        List<ExceptionDataExcel> excelList = new ArrayList<>();
        //如果没选择就导出所有的数据
        if (ids.size() == 0) {
            list = exceptionDataMapper.getAllListForExport();
        } else {
            //有选择就导出选择的数据
            list = exceptionDataMapper.getListForExport(ids);
        }
        ObjectMapper objectMapper = new ObjectMapper();
        for (ExceptionDataExcelVO vo : list) {
            List<Map<String, String>> data = objectMapper.readValue(vo.getFileList(), new TypeReference<List<Map<String, String>>>() {
            });
            List<String> urls = new ArrayList<>();
            for (Map<String, String> map : data) {
                urls.add(map.get("url"));
            }
            for (int i = 0; i < urls.size(); i++) {
                // 设置头像图片  创建一个单元格数据对象，并为其设置图片
                WriteCellData<Void> pictureCellData = new WriteCellData<>();
                pictureCellData.setType(CellDataTypeEnum.STRING);
                //下载图片并将其转换为字节数组
                URL imageUrl = new URL(urls.get(i));
                byte[] imageBytes = IOUtils.toByteArray(imageUrl.openStream());
                // 加载图片并设置到 ImageData 中
                // 创建图片数据并设置图片属性
                List<ImageData> imageDataList = new ArrayList<>();
                ImageData imageData = new ImageData();
                imageData.setImage(imageBytes);
                imageData.setImageType(ImageData.ImageType.PICTURE_TYPE_PNG);
                imageData.setTop(5);
                imageData.setRight(5);
                imageData.setBottom(5);
                imageData.setLeft(5);
                imageDataList.add(imageData);
                // 将图片数据列表加入单元格数据中
                pictureCellData.setImageDataList(imageDataList);
                if (i == 0) {
                    vo.setPicture1(pictureCellData);
                }
                if (i == 1) {
                    vo.setPicture2(pictureCellData);
                }
                if (i == 2) {
                    vo.setPicture3(pictureCellData);
                }
                if (i == 3) {
                    vo.setPicture4(pictureCellData);
                }
                if (i == 4) {
                    vo.setPicture5(pictureCellData);
                }
            }
            ExceptionDataExcel excel = exceptionDataConvert.voToExcel(vo);
            excelList.add(excel);

        }
        // 创建输出流
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        // 使用 EasyExcel 创建 Excel 写入器
        try {
            // 初始化写入器
            var excelWriter = EasyExcel.write(outputStream).head(ExceptionDataExcel.class).build();
            // 创建一个 WriteSheet 对象，用于指定工作表的名称
            WriteSheet writeSheet = EasyExcel.writerSheet("异常数据").head(getHead()).build();
            // 将所有数据写入这个工作表
            excelWriter.write(excelList, writeSheet);
            // 关闭写入器
            excelWriter.finish();
            // 设置响应头，指示浏览器下载
            response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
            response.setHeader("Content-Disposition", "attachment; filename=fileName.xlsx");
            // 写入输出流
            response.getOutputStream().write(outputStream.toByteArray());
            response.getOutputStream().flush();
        } finally {
        outputStream.close();
    }
        System.out.println("6666666666666666666666666666666666666666666666666666666");
    }


    /**
     * 导入
     * @param response
     * @param file
     * @return
     */
    @Override
    public void importExcel(HttpServletResponse response, MultipartFile file) throws IOException {
        ExcelUtil<ExceptionData> util = new ExcelUtil<ExceptionData>(ExceptionData.class);
        List<ExceptionData> exceptionDataList = util.importExcel(file.getInputStream());
        for(ExceptionData data :exceptionDataList){
            data.setFlagDel(0);
            data.setCreateTime(new Date());
            data.setEnter("");
            this.save(data);
        }
    }

    /**
     * 根据id查看图片详情
     * @param id
     * @return
     */
    @Override
    public String pictureDetails(Long id) {
        return exceptionDataMapper.getPictureDetails(id);
    }

    @Override
    public List<SkuVO> getListSku(String skuAll) {
        //查询出所有sku的数据
        List<SkuInfo> listSku = exceptionDataMapper.getSkuDetail();
        String[] skuArray = skuAll.split(",");
        List<SkuVO> list = new ArrayList<>();

        // 预定义常用BigDecimal常量，避免重复创建
        BigDecimal DIVISOR_1000 = new BigDecimal(1000);
        BigDecimal CONVERSION_FACTOR = new BigDecimal("0.0022046"); // 使用字符串构造精确值
        BigDecimal VOLUME_DIVISOR = new BigDecimal(9000);

        for (String sku : skuArray) {
            SkuVO vo = new SkuVO();
            vo.setSku(sku);
            for (SkuInfo skuInfo : listSku) {
                if (skuInfo.getSku().equals(sku)) {
                    // 长宽高
                    String[] size = skuInfo.getSize().split("\\*");
                    if (size.length != 3) {
                        continue; // 跳过格式不正确的尺寸数据
                    }

                    try {
                        vo.setLength(new BigDecimal(size[0]));
                        vo.setWidth(new BigDecimal(size[1]));
                        vo.setHeight(new BigDecimal(size[2]));

                        // 重量计算
                        vo.setWeight(skuInfo.getWeight().divide(DIVISOR_1000, 2, RoundingMode.HALF_UP));
                        vo.setWeightLB(skuInfo.getWeight().multiply(CONVERSION_FACTOR).setScale(2, RoundingMode.HALF_UP));

                        // 体积重计算
                        BigDecimal volume = vo.getLength()
                                .multiply(vo.getWidth())
                                .multiply(vo.getHeight())
                                .divide(VOLUME_DIVISOR, 2, RoundingMode.HALF_UP) // 添加精度控制
                                .multiply(new BigDecimal(2.2046))
                                .setScale(2, RoundingMode.HALF_UP);

                        vo.setBillingWeight(vo.getWeightLB().compareTo(volume) > 0 ? vo.getWeightLB() : volume);
                        //拿到报价的金额
                        List<String> scopeList = exceptionDataMapper.getScopePrice(skuInfo.getCustomerNickname());
                        if(skuInfo.getCustomerNickname().equals("SYKJ")){
                            if (vo.getBillingWeight().compareTo(BigDecimal.ZERO) > 0 && vo.getBillingWeight().compareTo(new BigDecimal("11")) <= 0) {
                                vo.setOperationFee(scopeList.get(0));
                            } else if (vo.getBillingWeight().compareTo(new BigDecimal("11")) > 0 && vo.getBillingWeight().compareTo(new BigDecimal("22")) <= 0) {
                                vo.setOperationFee(scopeList.get(1));
                            } else if (vo.getBillingWeight().compareTo(new BigDecimal("22")) > 0 && vo.getBillingWeight().compareTo(new BigDecimal("44")) <= 0) {
                                vo.setOperationFee(scopeList.get(2));
                            } else if (vo.getBillingWeight().compareTo(new BigDecimal("44")) > 0 && vo.getBillingWeight().compareTo(new BigDecimal("66")) <= 0) {
                                vo.setOperationFee(scopeList.get(3));
                            } else if (vo.getBillingWeight().compareTo(new BigDecimal("66")) > 0 && vo.getBillingWeight().compareTo(new BigDecimal("88")) <= 0) {
                                vo.setOperationFee(scopeList.get(4));
                            } else if (vo.getBillingWeight().compareTo(new BigDecimal("66")) > 0 && vo.getBillingWeight().compareTo(new BigDecimal("110")) <= 0) {
                                vo.setOperationFee(scopeList.get(5));
                            } else if (vo.getBillingWeight().compareTo(new BigDecimal("110")) > 0 && vo.getBillingWeight().compareTo(new BigDecimal("150")) <= 0) {
                                vo.setOperationFee(scopeList.get(6));
                            } else if (vo.getBillingWeight().compareTo(new BigDecimal("150")) > 0 ) {
                                vo.setOperationFee(scopeList.get(7));
                            }
                        }else if(skuInfo.getCustomerNickname().equals("NBJRMY")){
                            if (vo.getBillingWeight().compareTo(BigDecimal.ZERO) > 0 && vo.getBillingWeight().compareTo(new BigDecimal("1")) <= 0) {
                                vo.setOperationFee(scopeList.get(0));
                            } else if (vo.getBillingWeight().compareTo(new BigDecimal("1")) > 0 && vo.getBillingWeight().compareTo(new BigDecimal("3")) <= 0) {
                                vo.setOperationFee(scopeList.get(1));
                            } else if (vo.getBillingWeight().compareTo(new BigDecimal("3")) > 0 && vo.getBillingWeight().compareTo(new BigDecimal("7")) <= 0) {
                                vo.setOperationFee(scopeList.get(2));
                            } else if (vo.getBillingWeight().compareTo(new BigDecimal("7")) > 0 && vo.getBillingWeight().compareTo(new BigDecimal("11")) <= 0) {
                                vo.setOperationFee(scopeList.get(3));
                            } else if (vo.getBillingWeight().compareTo(new BigDecimal("11")) > 0 && vo.getBillingWeight().compareTo(new BigDecimal("28")) <= 0) {
                                vo.setOperationFee(scopeList.get(4));
                            } else if (vo.getBillingWeight().compareTo(new BigDecimal("28")) > 0 && vo.getBillingWeight().compareTo(new BigDecimal("44")) <= 0) {
                                vo.setOperationFee(scopeList.get(5));
                            } else if (vo.getBillingWeight().compareTo(new BigDecimal("44")) > 0 && vo.getBillingWeight().compareTo(new BigDecimal("66")) <= 0) {
                                vo.setOperationFee(scopeList.get(6));
                            } else if (vo.getBillingWeight().compareTo(new BigDecimal("66")) > 0 && vo.getBillingWeight().compareTo(new BigDecimal("88")) <= 0) {
                                vo.setOperationFee(scopeList.get(7));
                            } else if (vo.getBillingWeight().compareTo(new BigDecimal("88")) > 0 && vo.getBillingWeight().compareTo(new BigDecimal("110")) <= 0) {
                                vo.setOperationFee(scopeList.get(8));
                            } else if (vo.getBillingWeight().compareTo(new BigDecimal("110")) > 0 && vo.getBillingWeight().compareTo(new BigDecimal("150")) <= 0) {
                                vo.setOperationFee(scopeList.get(9));
                            } else if (vo.getBillingWeight().compareTo(new BigDecimal("150")) > 0) {
                                vo.setOperationFee(scopeList.get(10));
                            }
                        }else {
                            if (vo.getBillingWeight().compareTo(BigDecimal.ZERO) > 0 && vo.getBillingWeight().compareTo(new BigDecimal("1")) <= 0) {
                                vo.setOperationFee(scopeList.get(0));
                            } else if (vo.getBillingWeight().compareTo(new BigDecimal("1")) > 0 && vo.getBillingWeight().compareTo(new BigDecimal("3")) <= 0) {
                                vo.setOperationFee(scopeList.get(1));
                            } else if (vo.getBillingWeight().compareTo(new BigDecimal("3")) > 0 && vo.getBillingWeight().compareTo(new BigDecimal("7")) <= 0) {
                                vo.setOperationFee(scopeList.get(2));
                            } else if (vo.getBillingWeight().compareTo(new BigDecimal("7")) > 0 && vo.getBillingWeight().compareTo(new BigDecimal("11")) <= 0) {
                                vo.setOperationFee(scopeList.get(3));
                            } else if (vo.getBillingWeight().compareTo(new BigDecimal("11")) > 0 && vo.getBillingWeight().compareTo(new BigDecimal("22")) <= 0) {
                                vo.setOperationFee(scopeList.get(4));
                            } else if (vo.getBillingWeight().compareTo(new BigDecimal("22")) > 0 && vo.getBillingWeight().compareTo(new BigDecimal("44")) <= 0) {
                                vo.setOperationFee(scopeList.get(5));
                            } else if (vo.getBillingWeight().compareTo(new BigDecimal("44")) > 0 && vo.getBillingWeight().compareTo(new BigDecimal("66")) <= 0) {
                                vo.setOperationFee(scopeList.get(6));
                            } else if (vo.getBillingWeight().compareTo(new BigDecimal("66")) > 0 && vo.getBillingWeight().compareTo(new BigDecimal("88")) <= 0) {
                                vo.setOperationFee(scopeList.get(7));
                            } else if (vo.getBillingWeight().compareTo(new BigDecimal("88")) > 0 && vo.getBillingWeight().compareTo(new BigDecimal("110")) <= 0) {
                                vo.setOperationFee(scopeList.get(8));
                            } else if (vo.getBillingWeight().compareTo(new BigDecimal("110")) > 0 && vo.getBillingWeight().compareTo(new BigDecimal("150")) <= 0) {
                                vo.setOperationFee(scopeList.get(9));
                            } else if (vo.getBillingWeight().compareTo(new BigDecimal("150")) > 0) {
                                vo.setOperationFee(scopeList.get(10));
                            }
                        }
                        list.add(vo);
                    } catch (NumberFormatException e) {
                        continue;
                    } catch (Exception e) {
                        continue;
                    }
                    break;
                }
            }
        }
        return list;
    }

    @Override
    public void exportSku(HttpServletResponse response, List<SkuVO> skuVo) throws IOException {
        // 创建输出流
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        // 使用 EasyExcel 创建 Excel 写入器
        try {
            // 初始化写入器
            var excelWriter = EasyExcel.write(outputStream).head(SkuVO.class).build();
            // 创建一个 WriteSheet 对象，用于指定工作表的名称
            WriteSheet writeSheet = EasyExcel.writerSheet("sku").build();
            // 将所有数据写入这个工作表
            excelWriter.write(skuVo, writeSheet);
            // 关闭写入器
            excelWriter.finish();
            // 设置响应头，指示浏览器下载
            response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
            response.setHeader("Content-Disposition", "attachment; filename=fileName.xlsx");
            // 写入输出流
            response.getOutputStream().write(outputStream.toByteArray());
            response.getOutputStream().flush();
        } finally {
            outputStream.close();
        }
        System.out.println("6666666666666666666666666666666666666666666666666666666");
    }

    // 自定义方法获取标题
    private List<List<String>> getHead() {
        // 定义标题和对应的字段名称
        String[][] titlesAndFields = {
                {"日期"},
                {"客户"},
                {"上传部门"},
                {"上传人"},
                {"仓库"},
                {"问题点"},
                {"异常类型"},
                {"异常内容描述"},
                {"客户异常进度/结果"},
                {"确认人/部门"},
                {"图片1"},
                {"图片2"},
                {"图片3"},
                {"图片4"},
                {"图片5"},
        };
        // 使用流来创建标题列表
        List<List<String>> headList = Arrays.stream(titlesAndFields)
                .map(Arrays::asList)
                .collect(Collectors.toList());

        return headList;
    }


}
